﻿using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Microsoft.EntityFrameworkCore;
using pandx.Mulan.Authorization;
using pandx.Mulan.Authorization.Users;
using pandx.Mulan.Dictionaries.Dto;
using pandx.Mulan.Dictionaries.Exporting;
using pandx.Mulan.Dto;

namespace pandx.Mulan.Dictionaries
{
    public class DictionaryCategoryAppService:MulanAppServiceBase,IDictionaryCategoryAppService
    {
        private readonly IRepository<DictionaryCategory, long> _dictionaryCategoryRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly IDictionaryCategoryListExcelExporter _dictionaryCategoryListExcelExporter;

        public DictionaryCategoryAppService(
            IRepository<DictionaryCategory, long> dictionaryCategoryRepository,
            IRepository<User,long> userRepository,
            IDictionaryCategoryListExcelExporter dictionaryCategoryListExcelExporter
            )
        {
            _userRepository = userRepository;
            _dictionaryCategoryRepository = dictionaryCategoryRepository;
            _dictionaryCategoryListExcelExporter = dictionaryCategoryListExcelExporter;
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Browse)]
        public async Task<ListResultDto<DictionaryCategoryListDto>> ObtainDictionaryCategories(ObtainDictionaryCategoriesInput input)
        {

            var query = CreateDictionaryCategoryAndUsersQuery(input);

            var dictionaryCategoriesCount = await query.CountAsync();
            var dictionaryCategories = await query.ToListAsync();
            var dtos = dictionaryCategories.Select(item =>
            {
                var dto = ObjectMapper.Map<DictionaryCategoryListDto>(item.DictionaryCategory);
                dto.CreatorUserName = item.User.UserName;
                dto.CreatorName = item.User.Name;
                return dto;
            }).ToList();
            return new ListResultDto<DictionaryCategoryListDto>(dtos);
        }

        public async Task CreateOrUpdateDictionaryCategory(CreateOrUpdateDictionaryCategoryInput input)
        {
            if (input.DictionaryCategory.Id.HasValue)
            {
                await UpdateDictionaryCategoryAsync(input);
            }
            else
            {
                await CreateDictionaryCategoryAsync(input);
            }
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Update)]
        protected virtual async Task UpdateDictionaryCategoryAsync(CreateOrUpdateDictionaryCategoryInput input)
        {
            var dictionaryCategory = await _dictionaryCategoryRepository.GetAsync(input.DictionaryCategory.Id.Value);
            ObjectMapper.Map(input.DictionaryCategory, dictionaryCategory);
            await CurrentUnitOfWork.SaveChangesAsync();
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Create)]
        protected virtual async Task CreateDictionaryCategoryAsync(CreateOrUpdateDictionaryCategoryInput input)
        {
            if (AbpSession.TenantId.HasValue)
            {
            }
            var dictionaryCategory = ObjectMapper.Map<DictionaryCategory>(input.DictionaryCategory);

            dictionaryCategory.TenantId=AbpSession.TenantId;

            await _dictionaryCategoryRepository.InsertAsync(dictionaryCategory);
            await CurrentUnitOfWork.SaveChangesAsync();
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Create,AppPermissions.Pages_Administration_DictionaryCategories_Update)]
        public async Task<GetDictionaryCategoryForEditOutput> GetDictionaryCategoryForEdit(NullableIdDto<long> input)
        {
            var output = new GetDictionaryCategoryForEditOutput();
            if (input.Id.HasValue)
            {
                var dictionaryCategory = await _dictionaryCategoryRepository.GetAsync(input.Id.Value);
                output.DictionaryCategory = ObjectMapper.Map<DictionaryCategoryEditDto>(dictionaryCategory);
            }
            else
            {
                var dictionaryCategory = new DictionaryCategoryEditDto();
                output.DictionaryCategory = dictionaryCategory;
            }

            return output;
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Browse)]
        public async Task<DictionaryCategoryListDto> GetDictionaryCategory(EntityDto<long> input)
        {
            var dictionaryCategory = await _dictionaryCategoryRepository.GetAsync(input.Id);
            return ObjectMapper.Map<DictionaryCategoryListDto>(dictionaryCategory);
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Delete)]
        public async Task DeleteDictionaryCategory(EntityDto<long> input)
        {
            var dictionaryCategory = await _dictionaryCategoryRepository.GetAsync(input.Id);
            await _dictionaryCategoryRepository.DeleteAsync(input.Id);
        }

        // [AbpAuthorize(AppPermissions.Pages_DictionaryCategory_Export)]
        // public async Task<FileDto> ObtainDictionaryCategoriesToExcel(ObtainDictionaryCategoriesInput input)
        // {
        //     var dictionaryCategories = await CreateDictionaryCategoryAndUsersQuery(input).AsNoTracking().OrderBy(input.Sorting).ToListAsync();
        //     var dtos=dictionaryCategories.Select(item =>
        //     {
        //         var dto = ObjectMapper.Map<DictionaryCategoryListDto>(item.DictionaryCategory);
        //         dto.CreatorUserName = item.User.UserName;
        //         dto.CreatorName = item.User.Name;
        //         return dto;
        //     }).ToList();
        //     return _dictionaryCategoryListExcelExporter.ExportToExcel(dtos);
        // }

        private IQueryable<DictionaryCategoryAndUser> CreateDictionaryCategoryAndUsersQuery(ObtainDictionaryCategoriesInput input)
        {
            var query = from dictionaryCategory in _dictionaryCategoryRepository.GetAll()
                join user in _userRepository.GetAll() on dictionaryCategory.CreatorUserId equals user.Id into userJoin
                from joinedUser in userJoin.DefaultIfEmpty()
                select new DictionaryCategoryAndUser
                {
                    DictionaryCategory = dictionaryCategory,
                    User=joinedUser
                };

            query = query
                .WhereIf(!input.Filter.IsNullOrWhiteSpace(),
                    item => item.DictionaryCategory.Name.Contains(input.Filter) ||
                            item.DictionaryCategory.Code.Contains(input.Filter));
            return query;
            
        }
        [AbpAuthorize(AppPermissions.Pages_Administration_DictionaryCategories_Create,AppPermissions.Pages_Administration_DictionaryCategories_Update)]
        public async Task<ValidateOutput> ValidateCode(ValidateInput<string, int> input)
        {
            if (input.Id == 0)
            {
                var one = await _dictionaryCategoryRepository.GetAll().SingleOrDefaultAsync(r => r.Code == input.Value);
                if (one != null)
                {
                    return new ValidateOutput
                    {
                        Status = false,
                        Message = "字典分类代码 " + input.Value + " 已被占用"
                    };
                }
                else
                {
                    return new ValidateOutput
                    {
                        Status = true,
                    };
                }
            }
            else
            {
                var one = await _dictionaryCategoryRepository.GetAll().SingleOrDefaultAsync(r =>
                    r.Code == input.Value && r.Id != input.Id);
                if (one != null)
                {
                    return new ValidateOutput
                    {
                        Status = false,
                        Message = "字典分类代码 " + input.Value + " 已被占用"
                    };
                }
                else
                {
                    return new ValidateOutput
                    {
                        Status = true,
                    };
                }
            }
        }
    }
}
